package org.onvivals.app.ai.llm.model.coze;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.onvivals.app.ai.llm.AbstractLlmService;
import org.onvivals.module.iot.entity.IotDevice;
import org.onvivals.module.iot.entity.IotDeviceUser;
import org.onvivals.module.iot.service.IIotDeviceService;
import org.onvivals.module.iot.service.IIotDeviceUserService;
import org.onvivals.module.pms.entity.PmsHistory;
import org.onvivals.module.pms.entity.PmsRole;
import org.onvivals.module.pms.entity.vo.MessageVo;
import org.onvivals.module.pms.service.IPmsHistoryService;
import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSourceListener;
import okhttp3.sse.EventSources;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
public class CozeCloudService extends AbstractLlmService {

    private OkHttpClient okHttpClient;

	private JSONObject llmConfig;

	public PmsRole pmsRole;

	public CozeCloudService(JSONObject llmConfig, PmsRole roles) {
		this.okHttpClient = new OkHttpClient.Builder()
				.connectTimeout(1, TimeUnit.DAYS)
				.readTimeout(1, TimeUnit.DAYS)
				.build();
		this.llmConfig = llmConfig;
		this.pmsRole = roles;
	}


    @Override
    public void chat(String query, String userId, String productId, String deviceNum) {
        chat(query, userId, IdUtil.getSnowflakeNextIdStr(), deviceNum);
    }

    @Override
    public void chat(String query, String conversationId, String deviceNum) {
        sendChatRequest(query, deviceNum);
    }

    private void sendChatRequest(String query, String deviceNum) {
		String botId = this.llmConfig.getStr("bot_id");
		String token = this.llmConfig.getStr("personal_access_token");
		IPmsHistoryService pmsHistoryService = SpringUtil.getBean(IPmsHistoryService.class);
        List<PmsHistory> list = pmsHistoryService.list(Wrappers.<PmsHistory>lambdaQuery().eq(PmsHistory::getDeviceId,deviceNum));
		Integer maxMessageCount = pmsRole.getMaxMessageCount();
        if (list.size() > maxMessageCount){
            pmsHistoryService.remove(Wrappers.<PmsHistory>lambdaQuery().eq(PmsHistory::getDeviceId,deviceNum));
            list= new ArrayList<>();
        }
        if (CollUtil.isEmpty(list)){
			PmsHistory pmsHistorys = new PmsHistory();
            pmsHistorys.setDeviceId(deviceNum);
            pmsHistorys.setRole("user");
            pmsHistorys.setContent(query);
            pmsHistorys.insert();
            list.add(pmsHistorys);
        }else {
            PmsHistory pmsHistory = new PmsHistory();
            pmsHistory.setDeviceId(deviceNum);
            pmsHistory.setRole("user");
            pmsHistory.setContent(query);
            pmsHistory.insert();
            list.add(pmsHistory);
        }

        Map<String,Object> userMap = new HashMap<>();
        IIotDeviceService iotDeviceService = SpringUtil.getBean(IIotDeviceService.class);
        IotDevice iotDevice = iotDeviceService.selectDeviceBySerialNumber(deviceNum);
        if (iotDevice!=null){
            IIotDeviceUserService iotDeviceUser = SpringUtil.getBean(IIotDeviceUserService.class);
            IotDeviceUser deviceUser = iotDeviceUser.getOne(Wrappers.<IotDeviceUser>lambdaQuery().eq(IotDeviceUser::getDeviceId, iotDevice.getDeviceId()));
            userMap = BeanUtil.beanToMap(deviceUser,true,true);
            if (userMap!=null){
                userMap.remove("id");
                userMap.remove("device_id");
                userMap.remove("create_time");
                userMap.remove("update_time");
                userMap.remove("create_by");
                userMap.remove("update_by");
                userMap.remove("del_flag");
                userMap.put("bootName",iotDevice.getDeviceName());
            }else {
                userMap = new HashMap<>();
            }
        }
        List<MessageVo> messageVoList = BeanUtil.copyToList(list,MessageVo.class);
        messageVoList = messageVoList.parallelStream().filter(x-> StrUtil.isNotEmpty(x.getContent())).collect(Collectors.toUnmodifiableList());
        Map<String, Object> map = MapUtil.newHashMap();
        map.put("bot_id", botId);
        map.put("user_id", deviceNum);
        map.put("stream", true);
        map.put("auto_save_history",true);
        map.put("additional_messages",messageVoList);
		map.put("custom_variables",userMap);
        String requestJson = JSONUtil.toJsonPrettyStr(map);
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType,requestJson);
        Request request = new Request.Builder()
                .url("https://api.coze.cn/v3/chat")
                .addHeader("Authorization", "Bearer " + token)
                .addHeader("Content-Type", "application/json")
                .post(body)
                .build();
        EventSource.Factory factory = EventSources.createFactory(okHttpClient);
        EventSourceListener sourceListener = new CozeSSEEventSourceListener(pmsRole, deviceNum, query);
        //创建事件
        factory.newEventSource(request, sourceListener);
    }
}
